from rest_framework import viewsets, status, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, FormParser
from django_filters.rest_framework import DjangoFilterBackend
from django.http import HttpResponse
from django.db.models import Q
import json
import io
import zipfile
from datetime import datetime
from docx import Document
from docx.shared import Inches, Pt
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml.shared import OxmlElement, qn
from docx.oxml.ns import nsdecls, qn as qn_ns
import os
from django.conf import settings

from .models import RepairRecord, MaintenanceItem, RepairRecordImage
from .serializers import (
    RepairRecordSerializer, MaintenanceItemSerializer,
    RepairRecordListSerializer, MaintenanceItemListSerializer,
    RepairRecordImageSerializer
)


class RepairRecordViewSet(viewsets.ModelViewSet):
    """设备维修记录单视图集"""
    queryset = RepairRecord.objects.all().order_by('-create_time')
    serializer_class = RepairRecordSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['system_name', 'equipment_name', 'maintainer_name']
    search_fields = ['system_name', 'equipment_name', 'fault_description', 'record_number']
    ordering_fields = ['create_time', 'fault_date', 'completion_date']
    ordering = ['-create_time']
    
    def get_serializer_class(self):
        """根据动作选择序列化器"""
        # 始终返回完整的序列化器，确保所有字段都被包含
        return RepairRecordSerializer
    
    @action(detail=True, methods=['get'])
    def export_excel(self, request, pk=None):
        """导出单个维修记录为Excel"""
        try:
            record = self.get_object()
            
            # 创建CSV内容
            csv_content = [
                ['设备维修记录单'],
                ['No:', record.record_number],
                [''],
                ['系统名称', record.system_name, '设备名称', record.equipment_name],
                ['故障日期', record.fault_date or '', '设备编号', record.equipment_number or ''],
                ['故障描述：', record.fault_description or ''],
                [''],
                ['维修厂家名称', record.maintainer_name or '', '厂家联系人及电话', record.contact_phone or ''],
                ['维修方法：', record.maintenance_method or ''],
                [''],
                ['更换备件：', record.replacement_parts or ''],
                [''],
                ['完成日期', record.completion_date or '', '确认人', record.confirmer or ''],
                ['附图：', record.attachments or '']
            ]
            
            # 转换为CSV格式
            csv_text = '\n'.join([','.join([f'"{cell}"' for cell in row]) for row in csv_content])
            
            # 添加BOM以支持中文
            csv_with_bom = '\ufeff' + csv_text
            
            # 生成文件名
            today = datetime.now().strftime('%Y%m%d')
            filename = f'设备维修记录单_{record.record_number}_{today}.csv'
            
            response = HttpResponse(csv_with_bom, content_type='text/csv; charset=utf-8')
            response['Content-Disposition'] = f'attachment; filename="{filename}"'
            
            return response
            
        except Exception as e:
            return Response(
                {'error': f'导出失败: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    @action(detail=True, methods=['get'])
    def export_word(self, request, pk=None):
        """导出单个维修记录为Word文档"""
        try:
            record = self.get_object()
            
            # 创建Word文档
            doc = Document()
            
            # 设置字体和行间距函数
            def set_font(run, font_name='宋体', font_size=12):
                run.font.name = font_name
                run.font.size = Pt(font_size)
                run._element.rPr.rFonts.set(qn('w:eastAsia'), font_name)
            
            def set_line_spacing(paragraph, line_spacing=1.5):
                """设置段落行间距"""
                paragraph_format = paragraph.paragraph_format
                paragraph_format.line_spacing = line_spacing
            
            # 添加标题段落
            title_paragraph = doc.add_paragraph()
            title_paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
            set_line_spacing(title_paragraph, 1.5)
            
            # 添加标题（宋体三号，居中）
            title_run = title_paragraph.add_run('设备维修记录单')
            set_font(title_run, '宋体', 16)  # 三号字体约16pt
            title_run.bold = True
            
            # 添加No编号段落（右对齐）
            no_paragraph = doc.add_paragraph()
            no_paragraph.alignment = WD_ALIGN_PARAGRAPH.RIGHT
            set_line_spacing(no_paragraph, 1.5)
            no_run = no_paragraph.add_run(f'No: {record.record_number}')
            set_font(no_run, '宋体', 12)  # 小四号字体约12pt
            
            doc.add_paragraph('')  # 空行
            
            # 创建表格
            table = doc.add_table(rows=8, cols=4)
            table.style = 'Table Grid'
            
            # 设置表格字体和行间距函数
            def set_cell_font(cell, text, font_size=12):
                cell.text = text
                for paragraph in cell.paragraphs:
                    set_line_spacing(paragraph, 1.5)
                    for run in paragraph.runs:
                        set_font(run, '宋体', font_size)
            
            # 填充表格内容（宋体小四）
            cells = table.rows[0].cells
            set_cell_font(cells[0], '系统名称')
            set_cell_font(cells[1], record.system_name or '')
            set_cell_font(cells[2], '设备名称')
            set_cell_font(cells[3], record.equipment_name or '')
            
            cells = table.rows[1].cells
            set_cell_font(cells[0], '故障日期')
            set_cell_font(cells[1], str(record.fault_date) if record.fault_date else '')
            set_cell_font(cells[2], '设备编号')
            set_cell_font(cells[3], record.equipment_number or '')
            
            cells = table.rows[2].cells
            cells[0].merge(cells[1]).merge(cells[2]).merge(cells[3])
            set_cell_font(cells[0], f'故障描述：{record.fault_description or ""}')
            
            cells = table.rows[3].cells
            set_cell_font(cells[0], '维修厂家名称')
            set_cell_font(cells[1], record.maintainer_name or '')
            set_cell_font(cells[2], '厂家联系人及电话')
            set_cell_font(cells[3], record.contact_phone or '')
            
            cells = table.rows[4].cells
            cells[0].merge(cells[1]).merge(cells[2]).merge(cells[3])
            set_cell_font(cells[0], f'维修方法：{record.maintenance_method or ""}')
            
            cells = table.rows[5].cells
            cells[0].merge(cells[1]).merge(cells[2]).merge(cells[3])
            set_cell_font(cells[0], f'更换备件：{record.replacement_parts or ""}')
            
            cells = table.rows[6].cells
            set_cell_font(cells[0], '完成日期')
            set_cell_font(cells[1], str(record.completion_date) if record.completion_date else '')
            set_cell_font(cells[2], '确认人')
            set_cell_font(cells[3], record.confirmer or '')
            
            # 附图行
            cells = table.rows[7].cells
            cells[0].merge(cells[1]).merge(cells[2]).merge(cells[3])
            
            # 获取相关图片
            images = RepairRecordImage.objects.filter(repair_record=record)
            
            if images.exists():
                # 添加附图标题
                attachment_paragraph = cells[0].paragraphs[0]
                attachment_run = attachment_paragraph.add_run('附图：')
                set_font(attachment_run, '宋体', 12)
                
                # 添加图片
                for i, image in enumerate(images):
                    try:
                        # 添加换行
                        if i > 0:
                            attachment_paragraph.add_run('\n')
                        
                        # 添加图片到文档
                        if image.image and os.path.exists(image.image.path):
                            attachment_paragraph.add_run('\n')
                            run = attachment_paragraph.runs[-1]
                            run.add_picture(image.image.path, width=Inches(3))
                            
                            # 添加图片描述
                            if image.description:
                                desc_run = attachment_paragraph.add_run(f'\n{image.description}')
                                set_font(desc_run, '宋体', 10)
                    except Exception as img_error:
                        print(f'添加图片失败: {img_error}')
                        continue
            else:
                set_cell_font(cells[0], '附图：无')
            
            # 保存到内存
            doc_io = io.BytesIO()
            doc.save(doc_io)
            doc_io.seek(0)
            
            # 生成文件名
            today = datetime.now().strftime('%Y%m%d')
            filename = f'设备维修记录单_{record.record_number}_{today}.docx'
            
            response = HttpResponse(
                doc_io.getvalue(),
                content_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document'
            )
            response['Content-Disposition'] = f'attachment; filename="{filename}"'
            
            return response
            
        except Exception as e:
            return Response(
                {'error': f'导出Word失败: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    @action(detail=False, methods=['post'], parser_classes=[MultiPartParser, FormParser])
    def import_word(self, request):
        """导入Word文档"""
        try:
            file = request.FILES.get('file')
            if not file:
                return Response(
                    {'error': '请选择要导入的文件'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            if not file.name.lower().endswith(('.doc', '.docx')):
                return Response(
                    {'error': '只支持Word文档格式(.doc, .docx)'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 检查文件大小（限制为10MB）
            if file.size > 10 * 1024 * 1024:
                return Response(
                    {'error': '文件大小不能超过10MB'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            try:
                # 尝试使用python-docx解析Word文档
                import docx
                
                # 读取Word文档
                doc = docx.Document(file)
                
                # 提取文本内容
                text_content = []
                for paragraph in doc.paragraphs:
                    if paragraph.text.strip():
                        text_content.append(paragraph.text.strip())
                
                # 提取表格数据（结构化格式）
                tables_data = []
                for table in doc.tables:
                    table_data = []
                    for row in table.rows:
                        row_data = []
                        for cell in row.cells:
                            row_data.append(cell.text.strip())
                        table_data.append(row_data)
                    tables_data.append(table_data)
                
                # 也将表格内容添加到文本中（用于文本解析备用）
                for table in doc.tables:
                    for row in table.rows:
                        row_text = []
                        for cell in row.cells:
                            if cell.text.strip():
                                row_text.append(cell.text.strip())
                        if row_text:
                            text_content.append(' '.join(row_text))
                
                full_text = '\n'.join(text_content)
                
            except ImportError:
                # 如果没有安装python-docx，返回提示信息
                return Response(
                    {
                        'error': 'Word文档解析功能需要安装python-docx库',
                        'suggestion': '请运行: pip install python-docx'
                    }, 
                    status=status.HTTP_501_NOT_IMPLEMENTED
                )
            except Exception as doc_error:
                return Response(
                    {'error': f'Word文档解析失败: {str(doc_error)}'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            if not full_text or len(full_text.strip()) < 10:
                return Response(
                    {'error': 'Word文档内容为空或无法解析'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 使用工具函数解析维修记录
            from .utils import parse_repair_records_from_text, generate_record_number
            
            records = parse_repair_records_from_text(full_text, tables_data)
            
            if not records:
                return Response(
                    {
                        'error': '未找到有效的维修记录单信息',
                        'debug_info': {
                            'text_length': len(full_text),
                            'text_preview': full_text[:500] + '...' if len(full_text) > 500 else full_text,
                            'tables_count': len(tables_data) if tables_data else 0
                        }
                    }, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 保存解析出的记录
            created_records = []
            errors = []
            
            for i, record_data in enumerate(records):
                try:
                    # 导入时不自动生成记录编号，保持为空，需要用户手动填写
                    if not record_data.get('record_number'):
                        record_data['record_number'] = None
                    
                    serializer = self.get_serializer(data=record_data)
                    if serializer.is_valid():
                        record = serializer.save()
                        created_records.append(serializer.data)
                    else:
                        errors.append({
                            'index': i + 1,
                            'data': record_data,
                            'errors': serializer.errors
                        })
                except Exception as save_error:
                    errors.append({
                        'index': i + 1,
                        'data': record_data,
                        'errors': str(save_error)
                    })
            
            return Response({
                'message': f'Word文档导入完成',
                'total_found': len(records),
                'created': len(created_records),
                'failed': len(errors),
                'created_records': created_records,
                'errors': errors
            })
            
        except Exception as e:
            return Response(
                {'error': f'导入失败: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class MaintenanceItemViewSet(viewsets.ModelViewSet):
    """设备维护维保记录表视图集"""
    queryset = MaintenanceItem.objects.all().order_by('-create_time')
    serializer_class = MaintenanceItemSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['system_name', 'system_category', 'equipment_name', 'level']
    search_fields = ['system_name', 'equipment_name', 'content']
    ordering_fields = ['create_time', 'system_name']
    ordering = ['-create_time']
    
    def get_serializer_class(self):
        """根据动作选择序列化器"""
        if self.action == 'list':
            return MaintenanceItemListSerializer
        elif self.action == 'batch_create':
            return MaintenanceItemSerializer
        return MaintenanceItemSerializer
    
    @action(detail=False, methods=['get'])
    def categories(self, request):
        """获取所有系统分类"""
        categories = MaintenanceItem.SYSTEM_CATEGORY_CHOICES
        return Response({
            'categories': [{'value': choice[0], 'label': choice[1]} for choice in categories]
        })
    
    @action(detail=False, methods=['get'])
    def by_category(self, request):
        """按分类获取维保记录"""
        category = request.query_params.get('category')
        if not category:
            return Response(
                {'error': '请指定系统分类'}, 
                status=status.HTTP_400_BAD_REQUEST
            )
        
        queryset = self.get_queryset().filter(system_category=category)
        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['post'])
    def batch_create(self, request):
        """批量创建维保记录"""
        try:
            data = request.data
            if not isinstance(data, list):
                return Response(
                    {'error': '数据格式错误，应为数组'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            created_records = []
            errors = []
            
            for i, item_data in enumerate(data):
                serializer = self.get_serializer(data=item_data)
                if serializer.is_valid():
                    record = serializer.save()
                    created_records.append(serializer.data)
                else:
                    errors.append({
                        'index': i,
                        'errors': serializer.errors
                    })
            
            return Response({
                'created': len(created_records),
                'records': created_records,
                'errors': errors
            })
            
        except Exception as e:
            return Response(
                {'error': f'批量创建失败: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )


class RepairRecordImageViewSet(viewsets.ModelViewSet):
    """维修记录附图视图集"""
    queryset = RepairRecordImage.objects.all().order_by('-upload_time')
    serializer_class = RepairRecordImageSerializer
    parser_classes = [MultiPartParser, FormParser]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['repair_record']
    search_fields = ['original_filename', 'description']
    ordering_fields = ['upload_time']
    ordering = ['-upload_time']
    
    def get_serializer_context(self):
        """添加request到序列化器上下文"""
        context = super().get_serializer_context()
        context['request'] = self.request
        return context
    
    @action(detail=True, methods=['get'])
    def download(self, request, pk=None):
        """下载图片文件"""
        try:
            image = self.get_object()
            if not image.image:
                return Response(
                    {'error': '图片文件不存在'}, 
                    status=status.HTTP_404_NOT_FOUND
                )
            
            # 读取文件内容
            with open(image.image.path, 'rb') as f:
                file_content = f.read()
            
            # 设置响应头
            response = HttpResponse(
                file_content, 
                content_type='application/octet-stream'
            )
            response['Content-Disposition'] = f'attachment; filename="{image.original_filename}"'
            response['Content-Length'] = len(file_content)
            
            return response
            
        except FileNotFoundError:
            return Response(
                {'error': '图片文件不存在'}, 
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return Response(
                {'error': f'下载失败: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    @action(detail=True, methods=['get'])
    def preview(self, request, pk=None):
        """在线预览图片"""
        try:
            image = self.get_object()
            if not image.image:
                return Response(
                    {'error': '图片文件不存在'}, 
                    status=status.HTTP_404_NOT_FOUND
                )
            
            # 读取文件内容
            with open(image.image.path, 'rb') as f:
                file_content = f.read()
            
            # 根据文件扩展名设置content_type
            ext = image.original_filename.lower().split('.')[-1]
            content_type_map = {
                'jpg': 'image/jpeg',
                'jpeg': 'image/jpeg',
                'png': 'image/png',
                'gif': 'image/gif',
                'bmp': 'image/bmp',
                'webp': 'image/webp'
            }
            content_type = content_type_map.get(ext, 'image/jpeg')
            
            # 设置响应头
            response = HttpResponse(file_content, content_type=content_type)
            response['Content-Disposition'] = f'inline; filename="{image.original_filename}"'
            response['Content-Length'] = len(file_content)
            
            return response
            
        except FileNotFoundError:
            return Response(
                {'error': '图片文件不存在'}, 
                status=status.HTTP_404_NOT_FOUND
            )
        except Exception as e:
            return Response(
                {'error': f'预览失败: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    @action(detail=False, methods=['post'])
    def batch_upload(self, request):
        """批量上传图片"""
        try:
            repair_record_id = request.data.get('repair_record')
            if not repair_record_id:
                return Response(
                    {'error': '请指定维修记录ID'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 验证维修记录是否存在
            try:
                repair_record = RepairRecord.objects.get(id=repair_record_id)
            except RepairRecord.DoesNotExist:
                return Response(
                    {'error': '维修记录不存在'}, 
                    status=status.HTTP_404_NOT_FOUND
                )
            
            uploaded_images = []
            errors = []
            
            # 处理多个文件
            files = request.FILES.getlist('images')
            if not files:
                return Response(
                    {'error': '请选择要上传的图片文件'}, 
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            for i, file in enumerate(files):
                # 验证文件类型
                allowed_extensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp']
                file_ext = file.name.lower().split('.')[-1]
                if file_ext not in allowed_extensions:
                    errors.append({
                        'index': i,
                        'filename': file.name,
                        'error': f'不支持的文件格式: {file_ext}'
                    })
                    continue
                
                # 验证文件大小（限制为10MB）
                if file.size > 10 * 1024 * 1024:
                    errors.append({
                        'index': i,
                        'filename': file.name,
                        'error': '文件大小超过10MB限制'
                    })
                    continue
                
                # 创建图片记录
                data = {
                    'repair_record': repair_record_id,
                    'image': file,
                    'original_filename': file.name,
                    'description': request.data.get(f'description_{i}', '')
                }
                
                serializer = self.get_serializer(data=data)
                if serializer.is_valid():
                    image = serializer.save()
                    uploaded_images.append(serializer.data)
                else:
                    errors.append({
                        'index': i,
                        'filename': file.name,
                        'errors': serializer.errors
                    })
            
            return Response({
                'uploaded': len(uploaded_images),
                'images': uploaded_images,
                'errors': errors
            })
            
        except Exception as e:
            return Response(
                {'error': f'批量上传失败: {str(e)}'}, 
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
